﻿package Engine.RMI
{
    import Framework.Holder.*;
    import Framework.MQ.*;
    import Framework.Serialize.*;
    import Framework.Util.*;

    public class Session extends Object
    {
        private var _communicator:Communicator;
        private var _connection:RMIConnection;
        private var _messageMap:IDMap;
        private var _messageWaitToSend:Array;
        private var _bindingObject:Array;
        private var _keepActivePrx:IKeepActivePrxHelper;
        private var _name:String;
        private var _messageHandler:IMessageHandler;

        public function Session()
        {
            this._messageWaitToSend = new Array();
            this._bindingObject = new Array();
            this._messageMap = new IDMap();
            this._keepActivePrx = new IKeepActivePrxHelper();
            this._keepActivePrx.bindingSession(this);
        }

        public function get keepActivePrx() : IKeepActivePrx
        {
            return this._keepActivePrx;
        }

        public function get connection() : RMIConnection
        {
            return this._connection;
        }

        public function set connection(connection:RMIConnection) : void
        {
            this._connection = connection;
        }

        public function get communicator() : Communicator
        {
            return this._communicator;
        }

        public function set communicator(communicator:Communicator) : void
        {
            this._communicator = communicator;
        }

        public function get name() : String
        {
            return this._name;
        }

        public function set name(name:String) : void
        {
            this._name = name;
        }

        public function get messageHandler() : IMessageHandler
        {
            return this._messageHandler;
        }

        public function set messageHandler(messageHandler:IMessageHandler) : void
        {
            this._messageHandler = messageHandler;
        }

        public function bindCommunicator(communicator:Communicator) : void
        {
            if (this._connection != null)
            {
                this._connection.close();
                this._connection = null;
            }
            this.communicator = communicator;
            this.communicator.session = this;
        }

        public function removeBackObject(key:int) : Boolean
        {
            return this._messageMap.remove(key);
        }

        public function findRemoveBackObject(messageId:int) : RMIObjectBind
        {
            var rmiObjBind:RMIObjectBind = this._messageMap.findAndRemove(messageId) as RMIObjectBind;
            if (rmiObjBind != null)
            {
				rmiObjBind.resertTimer();
            }
            return rmiObjBind;
        }

        public function addBackObject(rmiObjBind:RMIObjectBind, time:int) : int
        {
            var _messagId:int = this._messageMap.insert(rmiObjBind);
            if (_messagId > 0)
            {
				rmiObjBind.initTimer(time);
            }
			
            return _messagId;
        }

        public function findObject(sidentity:SIdentity) : RMIObject
        {
            var obj:RMIObject = null;
            var i:int = 0;
            while (i < this._bindingObject.length)
            {
                
                obj = this._bindingObject[i] as RMIObject;
                if (obj.identity.name == sidentity.name)
                {
                    return obj;
                }
                i++;
            }
            return null;
        }

        public function bindingObject(sidentity:SIdentity, rmiObj:RMIObject) : Boolean
        {
            var obj:RMIObject = null;
            var i:int = 0;
            while (i < this._bindingObject.length)
            {
                
                obj = this._bindingObject[i] as RMIObject;
                if (obj.identity.name == sidentity.name)
                {
                    return false;
                }
                i++;
            }
            rmiObj.identity = sidentity;
            this._bindingObject.push(rmiObj);
            return true;
        }

        public function remove(sidentity:SIdentity) : Boolean
        {
            var rmiObj:RMIObject = null;
            var i:int = 0;
            while (i < this._bindingObject.size())
            {
                
                rmiObj = this._bindingObject[i] as RMIObject;
                if (rmiObj.identity.name == sidentity.name)
                {
                    this._bindingObject.splice(i, 1);
                    return true;
                }
                i++;
            }
            return false;
        }

        public function pushMessage(messageBlock:MessageBlock) : void
        {
            var stream:* = new SerializeStream();
            var context:* = new Context();
            context._session = this;
            context._connection = this.connection;
            context._messageId = 0;
            context._dispachStatus = ERMIDispatchStatus.DispatchAsync;
            context._messageType = ERMIMessageType.MessageTypeMQ;
            messageBlock.__write(stream);
            Outgoing.invokeAsyncNoBack(context, null, stream);
        }

        public function pinkMessage(holder:ArrayHolder) : void
        {
            holder.value = this._messageWaitToSend;
            this._messageWaitToSend = new Array();
        }

        public function pinkRemoveMessage(holder:ArrayHolder) : void
        {
            var rmiObjBind:RMIObjectBind = null;
            holder.value = new Array();
            var i:int = 0;
            var j:int = 0;
            while (j < this._messageWaitToSend.length)
            {
                
                rmiObjBind = this.findRemoveBackObject((this._messageWaitToSend[j] as RMIObjectBind).messageId);
                if (rmiObjBind != null)
                {
                    rmiObjBind.resertTimer();
                    holder.value[++i] = rmiObjBind;
                }
                j++;
            }
            this._messageWaitToSend = new Array();
        }

        public function addMessage(rmiObjBind:RMIObjectBind) : void
        {
            this._messageWaitToSend.push(rmiObjBind);
        }

        public function abandon() : void
        {
            if (this._connection != null)
            {
                this._connection.close();
                this._connection = null;
            }
            this._messageMap = new IDMap();
            this._messageWaitToSend = new Array();
            this._bindingObject = new Array();
        }

    }
}
